package net

import (
	"fmt"
	"strconv"
	"sync/atomic"
	"time"

	"gitee.com/cjianwen/go/demo/socks_v2/raft_demo/server/consts"
	"gitee.com/cjianwen/go/demo/socks_v2/raft_demo/server/global"
	"gitee.com/cjianwen/go/demo/socks_v2/raft_demo/server/proto"
	"gitee.com/cjianwen/go/logs"
	"gitee.com/cjianwen/go/service"
)

// 领导 或者 候选人才会用到

type client struct {
	receiver        *proto.MsgReceiver
	conn            *proto.ClientConn
	connAddr        string
	lastRecvMsgTime time.Time
}

func (c *client) connect() {
	logs.Println("连接到：", c.connAddr)
	c.conn = c.receiver.ConnectTo(c.connAddr)
}

func (c *client) close() {
	c.conn = nil
	c.receiver.CloseServe()
}

func (c *client) handleMsg() {
	c.receiver.HandlePacks(func(conn *proto.ConnClient, pack *proto.PackData) {
		c.lastRecvMsgTime = time.Now() // 记录下最后收消息的时间

		proto.DispatchMsg(conn, pack)
	})
}

type Connections struct {
	*service.Module

	clients []*client

	isConnect bool // 是否设置了连接
	connCount atomic.Int32
}

func (c *Connections) ConnCountIsOK() bool {
	return c.connCount.Load() >= int32(global.ServerInfo.ServerCountHalf) // 连接超过一半的服务器, 等于就可以，自己也算一台服务器
}

func (c *Connections) handleMsgs() {
	for _, client := range c.clients {
		client.handleMsg()
	}
}

func (c *Connections) ConnSvrs() {
	logs.Println("开始连接所有服务器")
	c.connCount.Store(0)
	for _, client := range c.clients {
		client.connect()
	}
	c.isConnect = true
}

func (c *Connections) CloseConns() {
	if c.isConnect {
		for _, client := range c.clients {
			client.close() // 关闭连接
		}
		c.isConnect = false
	}
}

func (c *Connections) GetConnCount() int {
	return int(c.connCount.Load())
}

func (c *Connections) SendPackToAll(pack *proto.PackData) error {
	tm := time.Now()
	for _, client := range c.clients {
		if client.conn.Connected() {
			if err := client.conn.SendPackToQueue(pack); err != nil {
				return fmt.Errorf("发送投票出错: %s", err)
			} else {
				if tm.Sub(client.lastRecvMsgTime).Milliseconds() > consts.PingTimeout {
					logs.Println("发送ping 超过过3次未响应, 断开重连")
					client.conn.Disconnect()
				}
			}
		}
	}
	return nil
}

func (c *Connections) Run() error {
	c.handleMsgs()
	return nil
}

func (c *Connections) Init() error {
	logs.Println("Connections.init")

	n := int(global.ServerInfo.ServerCount - 1)
	c.clients = make([]*client, n)
	idx := 0
	for i := 0; i < int(global.ServerInfo.ServerCount); i++ {
		port := i + 1 + consts.ServerPort
		if port != int(global.ServerInfo.GetListenPort()) { // 不连自己
			client := &client{}

			client.connAddr = "127.0.0.1:" + strconv.Itoa(port)

			client.receiver = proto.NewMsgReceiver()

			client.receiver.OnConnect = func(conn *proto.ConnClient) {
				client.lastRecvMsgTime = time.Now()
				n := c.connCount.Add(1)
				logs.Printf("客户端连接成功: %s, 当前连接数: %d", client.connAddr, n)
			}

			client.receiver.OnDisconnect = func(conn *proto.ConnClient) {
				n := c.connCount.Add(-1)
				logs.Printf("与服务器断开连接: %s, 当前连接数: %d", client.connAddr, n)
			}

			c.clients[idx] = client
			idx++
			if idx >= n {
				break
			}
		}
	}
	return nil
}

func (c *Connections) Final() error {
	logs.Println("Connections.Final")
	c.CloseConns()
	return nil
}

func init() { // 注册服务
	module := &service.Module{Name: "Connections", ModuleId: consts.MID_Connections}
	c := &Connections{Module: module}
	global.NodeConns = c
	service.RegisterModule(c)
}
